package com.pokeoffice.server;

import java.io.EOFException;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.net.Socket;
import java.util.List;
import java.util.Vector;

import com.pokeoffice.interfaces.Command;

/**
 * The Class Mediator.
 *
 * @author Kyle Davis
 * 
 * (Pattern: Singleton)
 */
public class Mediator {

	/** The mediator. */
	private static Mediator mediator = null;
	
	/** The router. */
	private Router router = null;
	
	/** The clients. */
	private List<ClientListener> clients = null;
	
	/**
	 * Instantiates a new mediator.
	 */
	private Mediator() {
		router = Router.get();
		clients = new Vector<ClientListener>();
	}

	/* (non-Javadoc)
	 * @see java.lang.Object#clone()
	 */
	public Object clone() throws CloneNotSupportedException {
		throw new CloneNotSupportedException();
	}
	
	/**
	 * Gets the.
	 *
	 * @return the mediator
	 */
	public static synchronized Mediator get() {
		if (mediator == null) {
			mediator = new Mediator();
		}
		
		return mediator;
	}
	
	/**
	 * Put client.
	 *
	 * @param sock the sock
	 */
	public void putClient(Socket sock) {
		ClientListener cl = new ClientListener(sock);
		cl.start();
		clients.add(cl);
	}

	/**
	 * Shutdown.
	 */
	public synchronized void shutdown() {
		for (int i = 0; i < clients.size(); i++) {
			ClientListener cl = clients.get(i);
			cl.shutdown();
		}
	}
	
	/**
	 * Update clients.
	 */
	public synchronized void updateClients() {
		
	}
	
	/**
	 * The listener interface for receiving client events.
	 * The class that is interested in processing a client
	 * event implements this interface, and the object created
	 * with that class is registered with a component using the
	 * component's <code>addClientListener<code> method. When
	 * the client event occurs, that object's appropriate
	 * method is invoked.
	 *
	 * @see ClientEvent
	 */
	private class ClientListener extends Thread {
		
		/** The sock. */
		private Socket sock;
		
		/** The ois. */
		private ObjectInputStream ois = null;
		
		/** The shutdown. */
		private boolean shutdown = false;
		
		/**
		 * Instantiates a new client listener.
		 *
		 * @param sock the sock
		 */
		private ClientListener(Socket sock) {
			this.sock = sock;
			
			try {
				ois = new ObjectInputStream(sock.getInputStream());
			} catch (IOException e) {
				e.printStackTrace();
			}
			
			shutdown = false;
		}
		
		/* (non-Javadoc)
		 * @see java.lang.Thread#run()
		 */
		public void run() {
			while(!shutdown) {
				try {
					Object obj = ois.readObject();
					if (obj != null && obj instanceof Command) {
						router.route((Command) obj);
					}
				} catch (EOFException e) {
					e.printStackTrace();
				} catch (IOException e) {
					e.printStackTrace();
				} catch (ClassNotFoundException e) {
					e.printStackTrace();
				}
			}
		}
		
		/**
		 * Shutdown.
		 */
		public synchronized void shutdown() {
			// FIXME
		}
	}
}
